﻿namespace LiveLabs.Logging
{
    using System;
    using System.Linq;
    using Xunit;

    public class LoggerNameFixture
    {
        private class Bar<T1, T2>
        {
            public static readonly LoggerName name = new LoggerName(typeof(Bar<T1, T2>));
        }

        [Fact]
        public void Should_Extract_Root_Name()
        {
            LoggerName n = new LoggerName("a.b.c.d");

            Assert.Equal("a.b.c.d", n.FullName);
            Assert.Equal("d", n.BaseName);
        }

        [Fact]
        public void Should_Be_Case_Insensitive_With_Equality()
        {
            LoggerName n1 = new LoggerName("a.B.c");
            LoggerName n2 = new LoggerName("A.b.C");

            Assert.Equal(n1, n2);
        }

        [Fact]
        public void Should_Be_Case_Insensitive_With_Comparison()
        {
            LoggerName n1 = new LoggerName("a.B.c");
            LoggerName n2 = new LoggerName("A.b.C");

            Assert.Equal(0, n1.CompareTo(n2));
        }

        [Fact]
        public void Should_Use_Fullname_Of_Type_For_Name()
        {
            LoggerName n = new LoggerName(typeof(Foo));

            Assert.Equal("LiveLabs.Logging.Foo", n.ToString());
        }

        [Fact]
        public void Should_Normalize_FullName_Of_Type_To_Use_Dot_For_Name()
        {
            LoggerName n = new LoggerName(typeof(Foo.Inner.Inner2));

            Assert.Equal("LiveLabs.Logging.Foo.Inner.Inner2", n.ToString());
        }

        [Fact]
        public void Should_Normalize_FullName_Of_Generic_Type_To_Use_Dot_For_Name()
        {
            LoggerName n = new LoggerName(typeof(Foo<string,int>));
            Assert.Equal("LiveLabs.Logging.Foo_2", n.ToString());

            n = new LoggerName(typeof(Foo<string, int>.Inner.Inner2<double>));
            Assert.Equal("LiveLabs.Logging.Foo_2.Inner.Inner2_1", n.ToString());

            n = new LoggerName(typeof(Foo<string, int, short>.Inner<float, double>.Inner2<DateTime>));
            Assert.Equal("LiveLabs.Logging.Foo_3.Inner_2.Inner2_1", n.ToString());

            n = new LoggerName(typeof(Foo<string, int, short>.Inner<float, double>.Inner3));
            Assert.Equal("LiveLabs.Logging.Foo_3.Inner_2.Inner3", n.ToString());

            n = new LoggerName(typeof(Foo<,,>.Inner<,>.Inner2<>));
            Assert.Equal("LiveLabs.Logging.Foo_3.Inner_2.Inner2_1", n.ToString());

            n = Bar<int, int>.name;
            Assert.Equal("LiveLabs.Logging.LoggerNameFixture.Bar_2", n.ToString());
        }

        [Fact]
        public void Should_Return_Hierarchy_Of_LoggerNames_In_Reverse_Order()
        {
            LoggerName n = new LoggerName(typeof(Foo.Inner.Inner2));

            LoggerName[] hierarchy = n.Hierarchy.ToArray();
            Assert.NotNull(hierarchy);
            Assert.Equal(5, hierarchy.Length);

            Assert.Equal(n, hierarchy[0]);
            Assert.Equal(new LoggerName(typeof(Foo.Inner)), hierarchy[1]);
            Assert.Equal(new LoggerName(typeof(Foo)), hierarchy[2]);
            Assert.Equal(new LoggerName("LiveLabs.Logging"), hierarchy[3]);
            Assert.Equal(new LoggerName("LiveLabs"), hierarchy[4]);
        }

        [Fact]
        public void Should_Return_Hierarchy_Of_One()
        {
            LoggerName n = new LoggerName("root");

            LoggerName[] hierarchy = n.Hierarchy.ToArray();
            Assert.NotNull(hierarchy);
            Assert.Equal(1, hierarchy.Length);

            Assert.Equal(n, hierarchy[0]);
        }
    }
}
